package WebserviceChecker;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import org.apache.hadoop.io.Text;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import Autodesk.ParseLogs;
import Autodesk.WebservReader;
import DatabaseManaging.DatabaseChecker;
import DatabaseManaging.JdbcChannelsDao;
import DatabaseManaging.JdbcLanguageDao;
import DatabaseManaging.JdbcProductsDao;
import DatabaseManaging.LanguageChannelDatabaseChecker;
import DatabaseManaging.ParametersDAO;
import DatabaseManaging.ProductDatabaseChecker;

public abstract class WbChecker {
	private static Logger logger = Logger.getLogger(ParseLogs.class);

	WebservReader webReader;
	DatabaseChecker dbchecker;
	public WbChecker() {
		WebservReader webReader = new WebservReader();
		this.webReader = webReader;	
	}

	public WbChecker(DatabaseChecker dbchecker) {
		super();
		WebservReader webReader = new WebservReader();
		this.webReader = webReader;
		this.dbchecker = dbchecker;
	}

	public ArrayList<String> checkWebService(Iterable<Text> inputValues){
			
		HashMap<String, String> ht = new HashMap<String, String>();
		ArrayList<String> parciaList=new ArrayList<String>();
		ArrayList<String> errorsList=new ArrayList<String>();
		try {
			System.out.println("Starting...");
			Iterator<Text> pattern= inputValues.iterator();
			while(pattern.hasNext()){
				String val=pattern.next().toString();
				String record[] = val.split("\t");
				ht=readWebService(record,ht);
				writeErrors(errorsList, ht);
				addFinalList(parciaList,ht);
			}
			logger.info("1"+parciaList);
			
			logger.info("Verifyng not to have repeated information..");
			parciaList=checkNotRepeatedBaseline(parciaList);
			logger.info("2-"+parciaList);
			
			logger.info("Checking not repeated information with the database,updating and inserting..");
			this.checkExistenceDatabase(parciaList);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Finished.");
		return errorsList;
	}

	
	private void checkExistenceDatabase(ArrayList<String> parciaList) {
		try {
			//dbchecker.findExistenceDatabase(parciaList, mappingFile);
			dbchecker.updateDatabase(parciaList);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

//	private void writeArchiveFromList(BufferedWriter fout, ArrayList<String> parciaList) throws IOException{
//		for(int i=0;i<parciaList.size();i++){
//			fout.write(parciaList.get(i).toString());
//			fout.write("\n");
//		}
//	}


///////////////////////////////////////////////////////////////////////////////////////
////////////////////////METHODS of CheckNotRepeatedBaseline////////////////////////////
	private ArrayList<String> checkNotRepeatedBaseline(
			ArrayList<String> listRaw) {
		ArrayList<String> result=new ArrayList<String>();
		ArrayList<String> halfResult=new ArrayList<String>();
		HashMap<String, String> mapAbbr=new HashMap<String, String>();
		
		//System.out.println("Length1: "+listRaw.size());
		
		mapAbbr=generateMapAbbreviations(listRaw);
		
		//System.out.println("Length2: "+listRaw.size()+" HashMap "+mapAbbr);
		
		halfResult=generateListWithoutRepeations(listRaw);
		
		//System.out.println(halfResult+ "Length: "+listRaw.size());
		
		result=generateFinalList(halfResult, mapAbbr);
		
		return result;
	}
	
	public ArrayList<String> generateFinalList(ArrayList<String> list,HashMap<String, String> mapAbbr){
		String resultReg;
		ArrayList<String> result=new ArrayList<String>();
		for(int i=0;i<list.size();i++){
			resultReg = generateRegToDatabase(list, i,mapAbbr);
			result.add(resultReg);
		}
		return result;		
	}
	
	public String generateRegToDatabase(ArrayList<String> list,
		int i, HashMap<String, String> mapAbbr) {
		String[] recordToAdd = list.get(i).split("\t");
		String abbr = "";
		String resultReg = null;
		abbr = mapAbbr.get(recordToAdd[1]);
		if (abbr == null) {
			abbr = "";
		}
		resultReg=generateReg(recordToAdd,abbr);
		return resultReg;
	}
	
	public abstract String generateReg(String[] records,String abbreviations);
	private ArrayList<String> generateListWithoutRepeations(ArrayList<String> listRaw){
		ArrayList<String> result=new ArrayList<String>();
		int i;
		for(i=0;i<listRaw.size();i++){
			for(int f=i+1;f<listRaw.size();f++){
				if(areEquals(listRaw.get(i), listRaw.get(f))){
					listRaw.remove(f);
				}
			}
			result.add(listRaw.get(i));
		}
		return result;
	}

	
	public abstract boolean areEquals(String string, String string2) ;

	public HashMap<String, String> generateMapAbbreviations(
			ArrayList<String> listRaw2) {
		HashMap<String, String> mapAbbr = new HashMap<String, String>();
		HashSet<String> listAbs = new HashSet();
		ArrayList<String> listRaw = new ArrayList<String>();
		listRaw=(ArrayList<String>)listRaw2.clone();
		
		String name;
		String abb;
		String[] record1;
		int i;
		for (i = 0; i < listRaw.size(); ++i) {
			abb = "";
			record1 = listRaw.get(i).split("\t");
			name = record1[1];

			if (!record1[2].equals("")) {
				listAbs.add(record1[2]);
			}
			for (int f = i + 1; f < listRaw.size(); ++f) {
				String[] record2 = listRaw.get(f).split("\t");
				if (name.equals(record2[1])){
					if (!record2[2].equals("") & !listAbs.contains(record2[2])) {
						listAbs.add(record2[2]);
					}
					listRaw.remove(f);

				}

			}
			if (!listAbs.isEmpty()) {
				String absSaved=mapAbbr.get(name);
				HashSet<String> listAbsMap = new HashSet();
				if(absSaved!=null){
					String[] recordSaved = absSaved.split("\t");
					for(int h=0;h<recordSaved.length;++h){
						listAbsMap.add(recordSaved[h]);
					}
					Iterator it=listAbs.iterator();	
					while(it.hasNext()){
						listAbsMap.add((String)it.next());
					}
					it=listAbsMap.iterator();
					while(it.hasNext()){
						abb = abb + it.next() + "\t";
					}
				}else{
					Iterator it=listAbs.iterator();	
					while(it.hasNext()){
						abb = abb + it.next() + "\t";
					}

				}
				mapAbbr.put(name, abb);
				listAbsMap.clear();
				
			}
			listAbs.clear();
		}

		return mapAbbr;
	}

///////////////////////////////////////////////////////////////////////////////////////

	public void addFinalList(ArrayList<String> parciaList,HashMap<String, String> ht) {
			if (ht.get("e") == null) {
				parciaList.add(ht.get("value"));
			}
		}

	public void writeErrors(ArrayList<String> errorsList,
			HashMap<String, String> ht) throws IOException {

		if(ht.get("e")!=null){
			System.out.println("Error: "+ht.get("value"));
		    errorsList.add(ht.get("value"));
		}
		
	}

	public abstract HashMap<String, String> readWebService(String[] record,
			HashMap<String, String> ht);
	
	public static void main(String[] args){
	    ApplicationContext context = new ClassPathXmlApplicationContext("application-context-persist.xml");
	    
//	    File finputLangs=new File(args[0]);
//	    File foutNotFoundLangs=new File(args[1]);
//	    File finputChann=new File(args[2]);
//	    File foutNotFoundChanns=new File(args[3]);
//	    File finputProd=new File(args[4]);
//	    File foutNotFoundProd=new File(args[5]);

	    JdbcLanguageDao dao=(JdbcLanguageDao) context.getBean("JdbcLanguagesDao");
	    LanguageChannelDatabaseChecker langchecker=new LanguageChannelDatabaseChecker();
	    langchecker.setJdbc(dao);
		ChannelLanguageChecker pdCheckerLangs=new ChannelLanguageChecker(langchecker);
		pdCheckerLangs.setParameter("languages");

	    JdbcChannelsDao dao2=(JdbcChannelsDao) context.getBean("JdbcChannelsDao");
	    LanguageChannelDatabaseChecker channelChecker=new LanguageChannelDatabaseChecker();
	    channelChecker.setJdbc(dao2);
		ChannelLanguageChecker pdCheckerChannel=new ChannelLanguageChecker(channelChecker);
		pdCheckerChannel.setParameter("channels");

		ParametersDAO dao3=(JdbcProductsDao) context.getBean("JdbcProductsDao");
	    ProductDatabaseChecker pdDBProd=new ProductDatabaseChecker();
	    pdDBProd.setJdbc(dao3);
	    ProductWbChecker pdCheckerProd=new ProductWbChecker(pdDBProd);
	    
		System.out.println("------------------------------Language Checking----------------------------------------");
		//pdCheckerLangs.checkWebService(foutNotFoundLangs);
		System.out.println("------------------------------Channel Checking----------------------------------------");
		//pdCheckerChannel.checkWebService(foutNotFoundChanns);
		System.out.println("------------------------------Product Checking----------------------------------------");
		//pdCheckerProd.checkWebService(foutNotFoundProd);		
		
	}
}

